/* $Id: UserFacadeImpl.java 
 * Copyright (C) 2011, TRAKHEES
 *  
 * Revision History
 *
 * Date  			Author 		    	Remarks
 * ---------------------------------------------------------------------------------
 *
 */
package ae.pcfc.etks.online.common.facade.provider;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate;
import ae.pcfc.etks.online.common.domain.TTscClientCompany;
import ae.pcfc.etks.online.common.domain.TTscClientPerson;
import ae.pcfc.etks.online.common.domain.User;
import ae.pcfc.etks.online.common.domain.UserStatusHistory;
import ae.pcfc.etks.online.common.domain.manager.SingleClientCompanyDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.SingleClientPersonDomainObjectManager;
import ae.pcfc.etks.online.common.domain.manager.UserDomainObjectManager;
import ae.pcfc.etks.online.common.facade.AppMetaDataFacade;
import ae.pcfc.etks.online.common.facade.UserFacade;
import ae.pcfc.etks.online.common.util.CommonUtils;
import ae.pcfc.etks.online.common.vo.ActivityVO;
import ae.pcfc.etks.online.common.vo.PagingVO;
import ae.pcfc.etks.online.common.vo.PasswordResetVO;
import ae.pcfc.etks.online.common.vo.SCCompanyVO;
import ae.pcfc.etks.online.common.vo.SCPersonVO;
import ae.pcfc.etks.online.common.vo.SearchCriteriaActivityVO;
import ae.pcfc.etks.online.common.vo.SearchCriteriaCompanyVO;
import ae.pcfc.etks.online.common.vo.SearchCriteriaPersonVO;
import ae.pcfc.etks.online.common.vo.UserDetailVO;
import ae.pcfc.etks.online.common.vo.UserVO;
import ae.pcfc.etks.online.common.vo.WorkflowRequestVO;
import ae.pcfc.etks.online.wf.service.client.ClientAdminWF;
import ae.pcfc.etks.online.wf.service.client.ClientRoleWF;
import ae.pcfc.etks.online.wf.service.client.NonClientWF;
import ae.pcfc.etks.online.wf.service.client.UserServiceWF;
import ae.pcfc.etks.online.wf.service.client.vo.ActiveTaskVO;
import ae.pcfc.etks.online.wf.service.client.vo.WFBaseVO;

public class UserFacadeImpl extends BaseFacade implements UserFacade {
	
	protected Map<String, String> webServicesEndPointsMap;
	
	@Resource(name = "ultWFWebServicesEndPointsMap")
    public void setWebServicesEndPointsMap(Map webServicesEndPointsMap) {
		this.webServicesEndPointsMap = webServicesEndPointsMap;
    }
    	/*
	 * Here we coordinate between the all interacting business domain objects
	 * (BO), transactions are maintained here. use case business validation are
	 * maintained here (that requires DB checks or retrieving data from DB)
	 */
	private UserDomainObjectManager userDomainObjectManager;

	public void setUserDomainObjectManager(
			UserDomainObjectManager userDomainObjectManager) {
		this.userDomainObjectManager = userDomainObjectManager;
	}

	private ClientRegistrationDelegate clientRegistrationDelegate;

	@Resource(name = "clientRegistrationDelegate")
	public void setClientRegistrationDelegate(
			ClientRegistrationDelegate clientRegistrationDelegate) {
		this.clientRegistrationDelegate = clientRegistrationDelegate;
	}
	
	private SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager;
	
	public void setSingleClientPersonDomainObjectManager(
			SingleClientPersonDomainObjectManager singleClientPersonDomainObjectManager) {
		this.singleClientPersonDomainObjectManager = singleClientPersonDomainObjectManager;
	}

	private SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager;
	
	public void setSingleClientCompanyDomainObjectManager(
			SingleClientCompanyDomainObjectManager singleClientCompanyDomainObjectManager) {
		this.singleClientCompanyDomainObjectManager = singleClientCompanyDomainObjectManager;
	}

	private AppMetaDataFacade appMetaDataFacade;
	
	public AppMetaDataFacade getAppMetaDataFacade() {
	    return appMetaDataFacade;
	}
	
	public void setAppMetaDataFacade(AppMetaDataFacade appMetaDataFacade) {
	    this.appMetaDataFacade = appMetaDataFacade;
	}

	private NonClientWF nonClientCompanyWFImpl;
	private NonClientWF nonClientPersonWFImpl;
	private ClientAdminWF clientCompanyAdminWF;
	private ClientAdminWF clientPersonAdminWF;
	private ClientRoleWF clientRoleWF;
	private UserServiceWF userServiceWF;
	
	public NonClientWF getNonClientCompanyWFImpl() {
	    return nonClientCompanyWFImpl;
	}
	public void setNonClientCompanyWFImpl(NonClientWF nonClientCompanyWFImpl) {
	    this.nonClientCompanyWFImpl = nonClientCompanyWFImpl;
	}

	public NonClientWF getNonClientPersonWFImpl() {
	    return nonClientPersonWFImpl;
	}
	public void setNonClientPersonWFImpl(NonClientWF nonClientPersonWFImpl) {
	    this.nonClientPersonWFImpl = nonClientPersonWFImpl;
	}

	public ClientAdminWF getClientCompanyAdminWF() {
	    return clientCompanyAdminWF;
	}
	public void setClientCompanyAdminWF(ClientAdminWF clientCompanyAdminWF) {
	    this.clientCompanyAdminWF = clientCompanyAdminWF;
	}

	public ClientAdminWF getClientPersonAdminWF() {
	    return clientPersonAdminWF;
	}
	public void setClientPersonAdminWF(ClientAdminWF clientPersonAdminWF) {
	    this.clientPersonAdminWF = clientPersonAdminWF;
	}

	public ClientRoleWF getClientRoleWF() {
	    return clientRoleWF;
	}

	public void setClientRoleWF(ClientRoleWF clientRoleWF) {
	    this.clientRoleWF = clientRoleWF;
	}

	public UserServiceWF getUserServiceWF() {
	    return userServiceWF;
	}

	public void setUserServiceWF(UserServiceWF userServiceWF) {
	    this.userServiceWF = userServiceWF;
	}

	/**
	 * getUserList
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#getUserList()
	 * 
	 */
	@Transactional(readOnly = true)
	public List<UserVO> getUserList() {

		List<User> userList = this.userDomainObjectManager.getUserList();
		List<UserVO> userVOs = new ArrayList<UserVO>();

		UserVO userVO;

		for (User user : userList) {
			userVO = new UserVO();
			getMapper().map(user, userVO);

			userVOs.add(userVO);
		}

		return (userVOs != null && userVOs.size() > 0) ? userVOs : null;
	}

	/**
	 * getUserListByPagingParameters
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#getUserListByPagingParameters(ae.pcfc.etks.online.common.vo.PagingVO)
	 * 
	 */
	@Transactional(readOnly = true)
	public List<UserVO> getUserListByPagingParameters(PagingVO pagingVO) {
		List<User> userList = this.userDomainObjectManager
				.getUserListByPagingParameters(pagingVO);
		if(userList == null){
			return null;
		}
		List<UserVO> userVOs = new ArrayList<UserVO>();

		UserVO userVO;

		if(userList != null){
			for (User user : userList) {
				userVO = new UserVO();
				getMapper().map(user, userVO);
	
				userVOs.add(userVO);
			}
		}

		return (userVOs != null && userVOs.size() > 0) ? userVOs : null;
	}

	/**
	 * findUserByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#findUserByUserName(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public UserVO findUserByUserName(String strUserName) {

		User user = this.userDomainObjectManager
				.findUserByUserName(strUserName);
		UserVO userVO = new UserVO();

		if (user != null)
			getMapper().map(user, userVO);

		return (userVO != null) ? userVO : null;
	}

	/**
	 * findUserByPrimaryKey
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#findUserByPrimaryKey(java.lang.Long)
	 * 
	 */
	@Transactional(readOnly = true)
	public UserVO findUserByPrimaryKey(Long id) {

		User user = this.userDomainObjectManager.findByPrimaryKey(String
				.valueOf(id));

		if (user != null) {
			UserVO userVO = new UserVO();
			getMapper().map(user, userVO);

			// Means it is an admin user that's why no client is attached
			if (!(userVO.getStrType().equals(ConstantsCommon.ADMIN) || userVO.getStrType().equals(ConstantsCommon.INTERNAL_TRAKHEES_STAFF)))
				userVO.setStrTrakheesId(user.getClient().getCTrakheesId());

			return userVO;
		}

		return null;
	}

	/**
	 * findUserByEmail
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#findUserByEmail(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public UserVO findUserByEmail(String email) {

		User user = this.userDomainObjectManager.findUserByEmail(email);

		if (user != null) {
			UserVO userVO = new UserVO();
			getMapper().map(user, userVO);
			return userVO;
		}
		return null;
	}

	/**
	 * resetPassword
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#resetPassword(ae.pcfc.etks.online.common.vo.PasswordResetVO)
	 * 
	 */
	@Transactional
	public void resetPassword(PasswordResetVO passwordResetVO) {

		// User user =
		// this.userDomainObjectManager.findUserByEmail(passwordResetVO.getStrEmail());
		User user = this.userDomainObjectManager.findByPrimaryKey(String
				.valueOf(passwordResetVO.getlUserId()));

		if (user != null) {

			user.setUPassword(passwordResetVO.getStrPassword());

			this.userDomainObjectManager.add(user);
		}

	}

	/**
	 * lockUser
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#lockUser(ae.pcfc.etks.online.common.vo.UserVO)
	 * 
	 */
	@Transactional
	public void lockUser(UserVO userVO) {

		User user = this.userDomainObjectManager.findByPrimaryKey(userVO
				.getlUserId().toString());
		this.getMapper().map(userVO, user);

		UserStatusHistory userStatusHistory = new UserStatusHistory();

		this.getMapper().map(userVO, userStatusHistory);
		userStatusHistory.setUser(user);

		if (user.getUserStatusHistories() != null) {

			user.getUserStatusHistories().add(userStatusHistory);

		} else {

			user.setUserStatusHistories(new HashSet<UserStatusHistory>(Arrays
					.asList(userStatusHistory)));
		}

		this.userDomainObjectManager.update(user);
	}

	/**
	 * addUser
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#addUser(ae.pcfc.etks.online.common.vo.UserVO)
	 * 
	 */
	@Transactional
	public void addUser(UserVO userVO) {
		// TODO Auto-generated method stub
		User user = new User();
		getMapper().map(userVO, user);
		this.userDomainObjectManager.add(user);
	}

	/**
	 * findUserDetailByUserName
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#findUserDetailByUserName(java.lang.String)
	 * 
	 */
	@Transactional(readOnly = true)
	public UserDetailVO findUserDetailByUserName(String strUserName) {

		User user = userDomainObjectManager.findUserByUserName(strUserName);
		UserVO userVO = new UserVO();
		UserDetailVO userDetailVO = new UserDetailVO();

		if (user == null)
			return null;
			
		
		getMapper().map(user, userVO);

		if (!(userVO.getStrType().equals(ConstantsCommon.ADMIN))) {
			String trakheesId = userVO.getClient().getStrTrakheesId();
			userVO.setStrTrakheesId(userVO.getClient().getStrTrakheesId());
			String[] client = trakheesId.split("-");

			if (client[0].equals(ConstantsCommon.COMPANY)) {
				userVO.setStrClientType(ConstantsCommon.COMPANY);
				SCCompanyVO companyVO = this.clientRegistrationDelegate
						.findSCCompanyByTrakheesId(trakheesId);
				userVO.setScCompanyVO(companyVO);
			} else if (client[0].equals(ConstantsCommon.PERSON))
				userVO.setStrClientType(ConstantsCommon.PERSON);
			{
				SCPersonVO personVO = clientRegistrationDelegate
						.findSCPersonByTrakheesId(trakheesId);
				userVO.setScPersonVO(personVO);
			}
		}

		getMapper().map(userVO, userDetailVO);

		return (userDetailVO != null) ? userDetailVO : null;
	}

	/**
	 * searchUsersByTrakheesId
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#searchUsersByTrakheesId(java.lang.String)
	 * 
	 */
	@Transactional(readOnly=true)
	public List<UserDetailVO> searchUsersByTrakheesId(String strTrakheesId){
		
		List<User> users = this.userDomainObjectManager.findUsersByTrakheesId(strTrakheesId);
		List<UserDetailVO> userDetailList = new ArrayList<UserDetailVO>();
		SCCompanyVO companyVO = null;
		SCPersonVO personVO = null;
		for(User user : users){
			UserVO userVO = new UserVO();
			UserDetailVO userDetailVO = new UserDetailVO();

			if (user != null)
				getMapper().map(user, userVO);

			if (!(userVO.getStrType().equals(ConstantsCommon.ADMIN))) {
				String trakheesId = userVO.getClient().getStrTrakheesId();
				userVO.setStrTrakheesId(userVO.getClient().getStrTrakheesId());
				String[] client = trakheesId.split("-");

				if (client[0].equals(ConstantsCommon.COMPANY)) {
					userVO.setStrClientType(ConstantsCommon.COMPANY);
					if(companyVO == null){
						companyVO = this.clientRegistrationDelegate
								.findSCCompanyByTrakheesId(trakheesId);
					}
					userVO.setScCompanyVO(companyVO);
				} else if (client[0].equals(ConstantsCommon.PERSON))
					userVO.setStrClientType(ConstantsCommon.PERSON);
				{
					if(personVO == null){
						personVO = clientRegistrationDelegate
								.findSCPersonByTrakheesId(trakheesId);
					}
					userVO.setScPersonVO(personVO);
				}
			}

			getMapper().map(userVO, userDetailVO);
			userDetailList.add(userDetailVO);
		}
		return userDetailList;
	}

	/**
	 * searchUsersByClientPerson
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#searchUsersByClientPerson(ae.pcfc.etks.online.common.vo.SearchCriteriaPersonVO)
	 * 
	 */
	@Transactional(readOnly=true)
	public List<UserDetailVO> searchUsersByClientPerson(SearchCriteriaPersonVO searchCriteriaPersonVO) {
		// TODO Auto-generated method stub
		List<TTscClientPerson> personsList = this.singleClientPersonDomainObjectManager.searchPerson(searchCriteriaPersonVO);
		List<UserDetailVO> userDetailList = new ArrayList<UserDetailVO>();
		if(personsList != null){
			for(TTscClientPerson person : personsList){
				if(person.getCpTrakheesId() != null){
					userDetailList =CommonUtils.union(userDetailList, searchUsersByTrakheesId(person.getCpTrakheesId()));
				}
			}
		}
		return userDetailList;
	}

	/**
	 * searchUsersByClientCompany
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#searchUsersByClientCompany(ae.pcfc.etks.online.common.vo.SearchCriteriaCompanyVO)
	 * 
	 */
	@Transactional(readOnly=true)
	public List<UserDetailVO> searchUsersByClientCompany(SearchCriteriaCompanyVO searchCriteriaCompanyVO) {
		// TODO Auto-generated method stub
		List<TTscClientCompany> companyList = this.singleClientCompanyDomainObjectManager.searchCompany(searchCriteriaCompanyVO);
		List<UserDetailVO> userDetailList = new ArrayList<UserDetailVO>();
		if(companyList != null){
			for(TTscClientCompany company : companyList){
				if(company.getCcTrakheesId() != null){
					userDetailList =CommonUtils.union(userDetailList, searchUsersByTrakheesId(company.getCcTrakheesId()));
				}
			}
		}
		return userDetailList;
	}

	/**
	 * findActivitiesOfClientCompany
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#findActivitiesOfClientCompany(ae.pcfc.etks.online.common.vo.SearchCriteriaActivityVO)
	 * 
	 */
	@Transactional(readOnly=true)
	public List<ActivityVO> findActivitiesOfClientCompany(SearchCriteriaActivityVO searchCriteriaActivityVO) {
		List<ActivityVO> activityList = this.singleClientCompanyDomainObjectManager.findActivitiesOfClientCompany(searchCriteriaActivityVO);
		return activityList;
	}

	/**
	 * getUserWorkflowRequests
	 * 
	 * @see ae.pcfc.etks.online.common.facade.UserFacade#getUserWorkflowRequests(java.lang.String)
	 * 
	 */
	public List<WorkflowRequestVO> getUserWorkflowRequests(String userName) {
	    WFBaseVO wfBaseVO = new WFBaseVO();
	    wfBaseVO.setStrUserName(userName);
	    List<WorkflowRequestVO> requestsList = new ArrayList<WorkflowRequestVO>();
	    List<ActiveTaskVO> activeTasksVOList = new ArrayList<ActiveTaskVO>();
	    List<ActiveTaskVO> ncprList = null;
	    
	    try {
		ncprList = nonClientPersonWFImpl.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	    if(ncprList!=null){
		activeTasksVOList.addAll(ncprList);
	    }

	    List<ActiveTaskVO> nccrList = null;
	    try {
		nccrList = nonClientCompanyWFImpl.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	    if(nccrList!=null){
		activeTasksVOList.addAll(nccrList);
	    }
	    
	    List<ActiveTaskVO> ccrList = null;
	    try {
		ccrList = clientCompanyAdminWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	    if(ccrList!=null){
		activeTasksVOList.addAll(ccrList);
	    }
	    
	    List<ActiveTaskVO> ccpList = null;
	    try {
		ccpList = clientPersonAdminWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	    if(ccpList!=null){
		activeTasksVOList.addAll(ccpList);
	    }
	    
	    List<ActiveTaskVO> rrList = null;
	    try {
		rrList = clientRoleWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	    if(rrList!=null){
		activeTasksVOList.addAll(rrList);
	    }
	    
	    List<ActiveTaskVO> srList = null;
	    try {
		srList = userServiceWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
	    if(srList!=null){
		activeTasksVOList.addAll(srList);
	    }
	    
	    if(activeTasksVOList.size() > 0){
		for(ActiveTaskVO taskVO : activeTasksVOList){
		    WorkflowRequestVO request = this.appMetaDataFacade.findByIncidentIDAndProcessCode(taskVO.getnIncidentNumber().toString(), taskVO.getStrProcessCode(),taskVO.getStrStepName());
		    if(request != null){
			request.setStrUsername(wfBaseVO.getStrUserName());
			requestsList.add(request);
		    }
		}
	    }
	    return (requestsList!=null &&requestsList.size()>0)?requestsList:null;
	}
	
	
	/*
	 * @Transactional(readOnly = true) public ClientCompanyVO
	 * userValidation(String userName, String password) {
	 * 
	 * User user = clientDomainObjectManager.userValidation(userName, password);
	 * if(user != null) { ClientCompanyVO clientCompanyVO = new
	 * ClientCompanyVO();
	 * clientCompanyVO.setStrCompNameArab(user.getUNameArb());
	 * clientCompanyVO.setStrCompNameEng(user.getUNameEng()); return
	 * clientCompanyVO; }else return null; }
	 */
	
	public List<String> getIncidentNoStepNames(Integer incidentNo, String processCode)
	{
	    WFBaseVO wfBaseVO = new WFBaseVO();
	    wfBaseVO.setStrUserName(webServicesEndPointsMap.get("UltimusAdminUser"));
	    
	    List<String> stepNames = new ArrayList<String>();
	    List<ActiveTaskVO> activeTasksVOList = new ArrayList<ActiveTaskVO>();
	    
	    
	    List<ActiveTaskVO> ncprList = null;
	    
	    try {
	    	ncprList = nonClientPersonWFImpl.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	    }
	    if(ncprList!=null){
	    	activeTasksVOList.addAll(ncprList);
	    }

	    List<ActiveTaskVO> nccrList = null;
	    try {
	    	nccrList = nonClientCompanyWFImpl.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	    }
	    if(nccrList!=null){
	    	activeTasksVOList.addAll(nccrList);
	    }
	    
	    List<ActiveTaskVO> ccrList = null;
	    try {
	    	ccrList = clientCompanyAdminWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	    }
	    if(ccrList!=null){
	    	activeTasksVOList.addAll(ccrList);
	    }
	    
	    List<ActiveTaskVO> ccpList = null;
	    try {
	    	ccpList = clientPersonAdminWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	    }
	    if(ccpList!=null){
	    	activeTasksVOList.addAll(ccpList);
	    }
	    
	    List<ActiveTaskVO> rrList = null;
	    try {
	    	rrList = clientRoleWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	    }
	    if(rrList!=null){
	    	activeTasksVOList.addAll(rrList);
	    }
	    
	    List<ActiveTaskVO> srList = null;
	    try {
	    	srList = userServiceWF.getActiveTasks(wfBaseVO);
	    } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	    }
	    if(srList!=null){
	    	activeTasksVOList.addAll(srList);
	    }
	    
	    if(activeTasksVOList.size() > 0)
	    {
			for(ActiveTaskVO taskVO : activeTasksVOList){
				if(taskVO.getnIncidentNumber().intValue() == incidentNo.intValue() && taskVO.getStrProcessCode().equals(processCode))
				{
					WorkflowRequestVO request = this.appMetaDataFacade.findByIncidentIDAndProcessCode(taskVO.getnIncidentNumber().toString(), taskVO.getStrProcessCode(),taskVO.getStrStepName());
					stepNames.add(request.getStrProcessStepDescEn());
				}
			}
	    }
	    return stepNames;
	}	
	

}
